﻿using Coldairarrow.Business.TD;
using Coldairarrow.Entity.Base;
using Coldairarrow.Entity.Base_Manage;
using Coldairarrow.Entity.DTO;
using Coldairarrow.Entity.IT;
using Coldairarrow.Entity.PB;
using Coldairarrow.Entity.TD;
using Coldairarrow.IBusiness;
using Coldairarrow.Util;
using EFCore.Sharding;
using LinqKit;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Coldairarrow.Business.IT
{
    public partial class IT_RecordBookBusiness : BaseBusiness<IT_RecordBook>, IIT_RecordBookBusiness, ITransientDependency
    {
        readonly IOperator _operator;
        readonly IOperatorDept _opdept;
        readonly IServiceProvider _ServiceProvider;
        public IT_RecordBookBusiness(IDbAccessor db, IServiceProvider svcProvider, IOperator @operator, IOperatorDept @opdept)
            : base(db)
        {
            _ServiceProvider = svcProvider;
            _operator = @operator;
            _opdept = @opdept;
        }

        #region 外部接口

        public async Task<PageResult<IT_RecordBook>> GetDataListAsync(PageInput<ConditionDTO> input)
        {
            var q = GetIQueryable();
            var where = LinqHelper.True<IT_RecordBook>();
            var search = input.Search;

            //筛选
            if (!search.Condition.IsNullOrEmpty() && !search.Keyword.IsNullOrEmpty())
            {
                var newWhere = DynamicExpressionParser.ParseLambda<IT_RecordBook, bool>(
                    ParsingConfig.Default, false, $@"{search.Condition}.Contains(@0)", search.Keyword);
                where = where.And(newWhere);
            }

            return await q.Where(where).GetPageResultAsync(input);
        }

        public async Task<IT_RecordBook> GetTheDataAsync(string id)
        {
            return await GetEntityAsync(id);
        }

        //public IQueryable<T> GetQueryable<T>() where T : class, new()
        //{
        //    return Db.GetIQueryable<T>();
        //}

        public async Task AddDataAsync(IT_RecordBook data)
        {
            await InsertAsync(data);
        }

        public async Task UpdateDataAsync(IT_RecordBook data)
        {
            await UpdateAsync(data);
        }

        public async Task DeleteDataAsync(List<string> ids)
        {
            await DeleteAsync(ids);
        }
        public async Task<PageResult<IT_RecordBookDTO>> GetDataListAsyncDtoList(PageInput<IT_RecordBookConditionDTO> input)
        {
            Expression<Func<IT_RecordBook, Base_Department, PB_Location, Base_Department, PB_Location, PB_Material, IT_RecordBookDTO>> select = (a, b, c, d, e, f) => new IT_RecordBookDTO
            {
                FromStorIdName = b.Name,
                FromLocalIdNName = c.Name,
                ToStorIdName = d.Name,
                ToLocalIdName = e.Name,
                MaterialIdName = f.Name,
            };
            var search = input.Search;
            select = select.BuildExtendSelectExpre();
            var q = from a in GetIQueryable().AsExpandable()
                    join b in Db.GetIQueryable<Base_Department>() on a.FromStorId equals b.Id into ab
                    from b in ab.DefaultIfEmpty()
                    join c in Db.GetIQueryable<PB_Location>() on a.FromLocalId equals c.Id into ac
                    from c in ac.DefaultIfEmpty()
                    join d in Db.GetIQueryable<Base_Department>() on a.ToStorId equals d.Id into ad
                    from d in ad.DefaultIfEmpty()
                    join e in Db.GetIQueryable<PB_Location>() on a.ToLocalId equals e.Id into ae
                    from e in ae.DefaultIfEmpty()
                    join f in Db.GetIQueryable<PB_Material>() on a.MaterialId equals f.Id into af
                    from f in af.DefaultIfEmpty()
                    select @select.Invoke(a, b, c, d, e, f);

            return await q.GetPageResultAsync(input);
        }

        /// <summary>
        /// Pc获取库存台账数据
        /// </summary>
        /// <param name="input">Seach</param>
        /// <returns></returns>
        public Task<PageResult<IT_RecordBookDtoList>> GetIT_RecordBookList(PageInput<IT_RecordBookDtoListSeach> input)
        {


            Expression<Func<IT_RecordBook, Base_Department, Base_Department, PB_Location, PB_Location, PB_Material, Base_User, Base_UnitItems, PB_StorArea, PB_Rack, PB_StorArea, PB_Rack, IT_RecordBookDtoList>> select = (a, b, c, d, e, f, g, k, f1, f2, f3, f4) => new IT_RecordBookDtoList
            {
                FromStorName = b.Name,
                ToStorName = c.Name,
                FromLocalName = f1.Name + "/" + f2.Name + "/" + d.Name,
                ToLocalName = f3.Name + "/" + f4.Name + "/" + e.Name,
                MaterialName = f.Name,
                ReallName = g.RealName,
                StorageName = k.Name,
                Weight = f.Weight.IsNullOrEmpty() ? 0 : f.Weight,
                TotalWeight = a.Num * (f.Weight.IsNullOrEmpty() ? 0 : f.Weight)
            };
            var search = input.Search;
            select = select.BuildExtendSelectExpre();
            var q = from a in GetIQueryable().AsExpandable()
                    join b in Db.GetIQueryable<Base_Department>() on a.FromStorId equals b.Id into ab
                    from b in ab.DefaultIfEmpty()
                    join c in Db.GetIQueryable<Base_Department>() on a.ToStorId equals c.Id into ac
                    from c in ac.DefaultIfEmpty()
                    join d in Db.GetIQueryable<PB_Location>() on a.FromLocalId equals d.Id into ad
                    from d in ad.DefaultIfEmpty()
                    join e in Db.GetIQueryable<PB_Location>() on a.ToLocalId equals e.Id into ae
                    from e in ae.DefaultIfEmpty()
                    join f in Db.GetIQueryable<PB_Material>() on a.MaterialId equals f.Id into af
                    from f in af.DefaultIfEmpty()
                    join g in Db.GetIQueryable<Base_User>() on a.CreatorId equals g.Id into ag
                    from g in ag.DefaultIfEmpty()
                    join k in Db.GetIQueryable<Base_UnitItems>() on f.storageId equals k.Id into fk
                    from k in fk.DefaultIfEmpty()
                    join f1 in Db.GetIQueryable<PB_StorArea>() on d.AreaId equals f1.Id into df1
                    from f1 in df1.DefaultIfEmpty()
                    join f2 in Db.GetIQueryable<PB_Rack>() on d.RackId equals f2.Id into df2
                    from f2 in df2.DefaultIfEmpty()
                    join f3 in Db.GetIQueryable<PB_StorArea>() on e.AreaId equals f3.Id into ef3
                    from f3 in ef3.DefaultIfEmpty()
                    join f4 in Db.GetIQueryable<PB_Rack>() on e.RackId equals f4.Id into ef4
                    from f4 in ef4.DefaultIfEmpty()
                    select @select.Invoke(a, b, c, d, e, f, g, k,f1,f2,f3,f4);
            //筛选条件
            if (!input.Search.RefCode.IsNullOrEmpty())
            {
                q = q.Where(m => m.RefCode.Contains(input.Search.RefCode));
            }
            if (!input.Search.Type.IsNullOrEmpty())
            {
                q = q.Where(m => m.Type == input.Search.Type);
            }
            if (!input.Search.GoLocation.IsNullOrEmpty())
            {
                q = q.Where(m => m.FromLocalName.Contains(input.Search.GoLocation) || m.ToLocalName.Contains(input.Search.GoLocation));
            }
            if (!input.Search.MaterSeach.IsNullOrEmpty())
            {
                q = q.Where(m => m.MaterialName.Contains(input.Search.MaterSeach));
            }

            return q.GetPageResultAsync(input);
        }

        /// <summary>
        /// 导入台账记录
        /// </summary>
        /// <param name="data">台账记录</param>
        /// <returns>提示</returns>
        //[Transactional(System.Data.IsolationLevel.Serializable)]
        //public async Task<string> ImportAsync(List<IT_RecordBook> data)
        //{
        //    var RecordBookTypes = Db.GetIQueryable<Base_EnumItem>().Where(m => m.EnumCode == "RecordBookType").ToList();
        //    List<IT_RecordBook> books = new List<IT_RecordBook>();
        //    for (int i = 0; i < data.Count; i++)
        //    {
        //        IT_RecordBook item = data[i];
        //        var book = await Db.GetIQueryable<IT_RecordBook>().Where(m => m.RefCode == item.RefCode && m.Type == item.Type).FirstOrDefaultAsync();
        //        if (book != null)
        //        {
        //            return "导入的第" + i.ToString() + @"行数据已存在数据库中,请不要重复导入！";
        //        }
        //        bool hasTypes = false;
        //        for (int j = 0; j < RecordBookTypes.Count; j++)
        //        {
        //            if (RecordBookTypes[j].Name == item.Type || RecordBookTypes[j].Value == item.Type)
        //            {
        //                item.Type = RecordBookTypes[j].Value;
        //                hasTypes = true;
        //                break;
        //            }
        //        }
        //        if (hasTypes)
        //        {
        //            string returnValue = await AddByTypeAsync(item.RefCode, item.Type);
        //            return returnValue;
        //        }
        //    }
        //    return string.Empty;
        //}
        /// <summary>
        /// 通过仓库操作主表Id和类型，添加台账记录
        /// </summary>
        /// <param name="refCode">仓库操作主表Id，非明细Id</param>
        /// <param name="type">仓库操作类型</param>
        /// <returns></returns>
        //public async Task<string> AddByTypeAsync(string refCode, string type)
        //{
        //    List<IT_RecordBook> books = await Db.GetIQueryable<IT_RecordBook>().Where(m => m.RefCode == refCode && m.Type == type).ToListAsync();
        //    if (books.Count == 0)
        //    {
        //        switch (type)
        //        {
        //            case "In":
        //                var inStorage = await Db.GetIQueryable<TD_InStorage>().Where(m => m.Id == refCode).FirstOrDefaultAsync();
        //                if (inStorage == null)
        //                {
        //                    return "台账数据提交失败：入库数据不存在！";
        //                }
        //                else
        //                {
        //                    var inDetails = await Db.GetIQueryable<TD_InStorDetail>().Where(m => m.InStorId == refCode).ToListAsync();
        //                    inDetails.ForEach(aData =>
        //                    {
        //                        IT_RecordBook aBook = new IT_RecordBook();
        //                        aBook.Id = IdHelper.GetId();
        //                        aBook.Type = type;
        //                        aBook.CreatorId = aData.CreatorId;
        //                        aBook.CreateTime = aData.CreateTime;
        //                        aBook.Deleted = false;
        //                        aBook.RefCode = aData.InStorId;
        //                        aBook.ToStorId = aData.StorId;
        //                        aBook.ToLocalId = aData.LocalId;
        //                        aBook.MaterialId = aData.MaterialId;
        //                        var material = Db.GetIQueryable<PB_Material>().Where(m => m.Id == aData.MaterialId).FirstOrDefault();
        //                        aBook.MeasureId = material.storageId;
        //                        aBook.BarCode = material.BarCode;
        //                        aBook.Num = aData.Num;
        //                        aBook.BatchNo = aData.BatchNo;
        //                        books.Add(aBook);
        //                    });
        //                }
        //                break;
        //            case "Out":
        //                var outStorage = await Db.GetIQueryable<TD_OutStorage>().Where(m => m.Id == refCode).FirstOrDefaultAsync();
        //                if (outStorage == null)
        //                {
        //                    return "台账数据提交失败：出库数据不存在！";
        //                }
        //                var outDetails = await Db.GetIQueryable<TD_OutStorDetail>().Where(m => m.OutStorId == refCode).ToListAsync();
        //                outDetails.ForEach(aData =>
        //                {
        //                    IT_RecordBook aBook = new IT_RecordBook();
        //                    aBook.Id = IdHelper.GetId();
        //                    aBook.Type = type;
        //                    aBook.CreatorId = aData.CreatorId;
        //                    aBook.CreateTime = aData.CreateTime;
        //                    aBook.Deleted = false;
        //                    aBook.RefCode = aData.OutStorId;
        //                    aBook.FromStorId = aData.StorId;
        //                    aBook.FromLocalId = aData.LocalId;
        //                    aBook.MaterialId = aData.MaterialId;
        //                    var material = Db.GetIQueryable<PB_Material>().Where(m => m.Id == aData.MaterialId).FirstOrDefault();
        //                    aBook.MeasureId = material.storageId;
        //                    aBook.BarCode = material.BarCode;
        //                    aBook.Num = aData.OutNum;
        //                    aBook.BatchNo = aData.BatchNo;
        //                    books.Add(aBook);
        //                });
        //                break;
        //            case "Move":
        //                var moveStorage = await Db.GetIQueryable<TD_Move>().Where(m => m.Id == refCode).FirstOrDefaultAsync();
        //                if (moveStorage == null)
        //                {
        //                    return "台账数据提交失败：移库数据不存在！";
        //                }
        //                var moveDetails = await Db.GetIQueryable<TD_MoveDetail>().Where(m => m.MoveId == refCode).ToListAsync();
        //                moveDetails.ForEach(aData =>
        //                {
        //                    IT_RecordBook aBook = new IT_RecordBook();
        //                    aBook.Id = IdHelper.GetId();
        //                    switch (moveStorage.Type)
        //                    {
        //                        case "UpMove":
        //                            aBook.Type = "MoveIn";
        //                            break;
        //                        case "StorMove":
        //                            aBook.Type = "MoveOut";
        //                            break;
        //                        case "BadMove":
        //                            aBook.Type = "BadOut";
        //                            break;
        //                        default:
        //                            break;
        //                    }
        //                    aBook.CreatorId = aData.CreatorId;
        //                    aBook.CreateTime = aData.CreateTime;
        //                    aBook.Deleted = false;
        //                    aBook.RefCode = aData.MoveId;
        //                    PB_Location fromLoc = Db.GetIQueryable<PB_Location>().Where(m => m.Id == aData.FromLocalId).FirstOrDefault();
        //                    if (fromLoc != null)
        //                    {
        //                        aBook.FromStorId = fromLoc.StorId;
        //                    }
        //                    aBook.FromLocalId = aData.FromLocalId;
        //                    PB_Location toLoc = Db.GetIQueryable<PB_Location>().Where(m => m.Id == aData.ToLocalId).FirstOrDefault();
        //                    if (toLoc != null)
        //                    {
        //                        aBook.ToStorId = toLoc.StorId;
        //                    }
        //                    aBook.ToLocalId = aData.ToLocalId;
        //                    aBook.MaterialId = aData.MaterialId;
        //                    PB_Material mater = Db.GetIQueryable<PB_Material>().Where(m => m.Id == aData.MaterialId).FirstOrDefault();
        //                    aBook.MeasureId = mater.storageId;
        //                    aBook.BarCode = mater.BarCode;
        //                    aBook.BatchNo = aData.BatchNo;
        //                    aBook.Num = aData.LocalNum;
        //                    books.Add(aBook);
        //                });
        //                break;
        //            default:
        //                break;
        //        }
        //    }
        //    if (books.Count > 0)
        //    {
        //        try
        //        {
        //            await AddDataAsync(books);
        //        }
        //        catch (Exception ex)
        //        {
        //            return "台账数据提交失败：" + ex.Message;
        //        }
        //    }
        //    else
        //    {
        //        return "台账数据无增加";
        //    }
        //    return string.Empty;
        //}
        /// <summary>
        /// 通过仓库操作明细表Id和类型，添加台账记录
        /// </summary>
        /// <param name = "detailId" > 仓库操作明细表Id，非明细Id</param>
        /// <param name = "type" > 仓库操作类型 </param >
        /// <returns >操作提示</returns >
        public async Task<string> AddDetailByTypeAsync(string detailId, string type)
        {
            IT_RecordBook aBook = new IT_RecordBook();
            PB_Material material;
            switch (type)
            {
                case "In":
                    var inDetail = await Db.GetIQueryable<TD_InStorDetail>().Where(m => m.Id == detailId).FirstOrDefaultAsync();
                    if (inDetail == null)
                    {
                        return "台账数据提交失败：入库明细数据不存在！";
                    }
                    else
                    {
                        aBook = new IT_RecordBook();
                        aBook.Id = IdHelper.GetId();
                        var inStorage = await Db.GetIQueryable<TD_InStorage>().Where(m => m.Id == inDetail.InStorId).FirstOrDefaultAsync();
                        if (inStorage == null)
                        {
                            return "台账数据提交失败：入库数据不存在！";
                        }
                        aBook.Type = inStorage.InType;
                        aBook.CreatorId = inDetail.CreatorId;
                        aBook.CreateTime = inDetail.CreateTime;
                        aBook.Deleted = false;
                        aBook.RefCode = inDetail.InStorId;
                        aBook.ToStorId = inDetail.StorId;
                        aBook.ToLocalId = inDetail.LocalId;
                        aBook.MaterialId = inDetail.MaterialId;
                        material = Db.GetIQueryable<PB_Material>().Where(m => m.Id == inDetail.MaterialId).FirstOrDefault();
                        aBook.MeasureId = material.storageId;
                        aBook.BarCode = material.BarCode;
                        aBook.Num = inDetail.Num;
                        aBook.BatchNo = inDetail.BatchNo;
                    }
                    break;
                case "Out":
                    var outDetail = await Db.GetIQueryable<TD_OutStorDetail>().Where(m => m.Id == detailId).FirstOrDefaultAsync();
                    if (outDetail == null)
                    {
                        return "台账数据提交失败：出库明细数据不存在！";
                    }
                    aBook = new IT_RecordBook();
                    aBook.Id = IdHelper.GetId();
                    var outStorage = await Db.GetIQueryable<TD_OutStorage>().Where(m => m.Id == outDetail.OutStorId).FirstOrDefaultAsync();
                    if (outStorage == null)
                    {
                        return "台账数据提交失败：出库数据不存在！";
                    }
                    aBook.Type = outStorage.OutType;
                    aBook.CreatorId = outDetail.CreatorId;
                    aBook.CreateTime = outDetail.CreateTime;
                    aBook.Deleted = false;
                    aBook.RefCode = outDetail.OutStorId;
                    aBook.FromStorId = outDetail.StorId;
                    aBook.FromLocalId = outDetail.LocalId;
                    aBook.MaterialId = outDetail.MaterialId;
                    material = Db.GetIQueryable<PB_Material>().Where(m => m.Id == outDetail.MaterialId).FirstOrDefault();
                    aBook.MeasureId = material.storageId;
                    aBook.BarCode = material.BarCode;
                    aBook.Num = outDetail.OutNum;
                    aBook.BatchNo = outDetail.BatchNo;
                    break;
                case "Move":
                    var moveDetail = await Db.GetIQueryable<TD_MoveDetail>().Where(m => m.Id == detailId).FirstOrDefaultAsync();
                    if (moveDetail == null)
                    {
                        return "台账数据提交失败：移库明细数据不存在！";
                    }

                    aBook = new IT_RecordBook();
                    aBook.Id = IdHelper.GetId();
                    var moveStorage = await Db.GetIQueryable<TD_Move>().Where(m => m.Id == moveDetail.MoveId).FirstOrDefaultAsync();
                    if (moveStorage == null)
                    {
                        return "台账数据提交失败：移库数据不存在！";
                    }
                    aBook.Type = moveStorage.Type;
                    //switch (moveStorage.Type)
                    //{
                    //    case "UpMove":
                    //        aBook.Type = "MoveIn";
                    //        break;
                    //    case "StorMove":
                    //        aBook.Type = "MoveOut";
                    //        break;
                    //    case "BadMove":
                    //        aBook.Type = "BadOut";
                    //        break;
                    //    default:
                    //        break;
                    //}
                    aBook.CreatorId = moveDetail.CreatorId;
                    aBook.CreateTime = moveDetail.CreateTime;
                    aBook.Deleted = false;
                    aBook.RefCode = moveDetail.MoveId;
                    PB_Location fromLoc = Db.GetIQueryable<PB_Location>().Where(m => m.Id == moveDetail.FromLocalId).FirstOrDefault();
                    if (fromLoc != null)
                    {
                        aBook.FromStorId = fromLoc.StorId;
                    }
                    aBook.FromLocalId = moveDetail.FromLocalId;
                    PB_Location toLoc = Db.GetIQueryable<PB_Location>().Where(m => m.Id == moveDetail.ToLocalId).FirstOrDefault();
                    if (toLoc != null)
                    {
                        aBook.ToStorId = toLoc.StorId;
                    }
                    aBook.ToLocalId = moveDetail.ToLocalId;
                    aBook.MaterialId = moveDetail.MaterialId;
                    material = Db.GetIQueryable<PB_Material>().Where(m => m.Id == moveDetail.MaterialId).FirstOrDefault();
                    if (material != null)
                    {
                        aBook.MeasureId = material.storageId;
                        aBook.BarCode = material.BarCode;
                    }
                    aBook.BatchNo = moveDetail.BatchNo;
                    aBook.Num = moveDetail.LocalNum;
                    break;
                default:
                    break;
            }
            try
            {
                await AddDataAsync(aBook);
            }
            catch (Exception ex)
            {
                return "台账数据提交失败：" + ex.Message;
            }
            return string.Empty;
        }
        #endregion

        #region 私有成员

        #endregion
    }
}